/**
 * @file Ball.cpp
 * Implementation of the Ball class
 * @author Timmy Nelen
 * @date Created on: Nov 18, 2010
 */

#include "Ball.h"

/**
 * Constructor of a ball object
 *
 * @param[in] x The X position of the ball
 * @param[in] y The Y position of the ball
 * @param[in] rad The radius of the ball
 * @param[in] xVel The XVelocity of the ball
 * @param[in] yVel The YVelocity of the ball
 */
bo::Ball::Ball(const double x, const double y, const double rad, const double xVel, const double yVel)
	: MovableEntity(x, y, rad){
	this->fXVel = xVel;
	this->fYVel = yVel;
}

bo::Ball::~Ball() {

}

/**
 * Makes the ball bounce off another entity and resets the position when they're penetrating
 *
 * @param[in] ent The entity the ball bounces against
 */
void bo::Ball::Bounce(Entity* ent){
	// Fixes ball when it "penetrates" another ball.
	double angle = std::atan2(ent->GetPos().GetY() - this->GetPos().GetY(),
								ent->GetPos().GetX() - this->GetPos().GetX());
	double circDist = sqrt(pow(ent->GetPos().GetX() - this->GetPos().GetX(), 2) +
							pow(ent->GetPos().GetY() - this->GetPos().GetY(), 2));
	double toMove = this->GetRadius() + ent->GetRadius() - circDist;
	this->GetPos().SetX(this->GetPos().GetX() + std::cos(angle) * toMove);
	this->GetPos().SetY(this->GetPos().GetY() + std::cos(angle) * toMove);
	// Uit cursus GFX:
	
	//Vector perpendicular to the vector between the 2 centers
	Vector2 tangentVector(ent->GetPos().GetY() - this->GetPos().GetY(),
								-( ent->GetPos().GetX() - this->GetPos().GetX() ) );
	tangentVector.Normalize();
	// The (normal)vector between the 2 centers
	Vector2 normalVect(ent->GetPos().GetX() - this->GetPos().GetX(), ent->GetPos().GetY() - this->GetPos().GetY());
	normalVect.Normalize();
	// Vectorise the velocity
	Vector2 velVect(this->fXVel, this->fYVel);
	double norm = velVect.Norm(); // Save original norm so I can restore the speed of the ball later.
	velVect.Normalize();
	// Dotproduct between the velocityvector and the normalvector
	double alpha = velVect.DotProd(normalVect);
	// Reflection vector (credits: Graphics, 1st year)
	Vector2 refVector = normalVect * 2 * std::cos(alpha) - velVect;
	// Normalise and "reset" the velocity to its original speed
	refVector.Normalize();
	this->fXVel = -refVector.GetX() * norm;
	this->fYVel = -refVector.GetY() * norm;
}

/**
 * Returns X component of velocity
 *
 * @return The X component of the ball's velocity
 */
double bo::Ball::GetXVelocity(){
	return fXVel;
}

/**
 * Returns Y component of velocity
 *
 * @return The Y component of the ball's velocity
 */
double bo::Ball::GetYVelocity(){
	return fYVel;
}

/**
 * Sets the initial velocity
 *
 * @param[in] xVel The XVelocity to be used
 * @param[in] yVel The YVelocity to be used
 */
void bo::Ball::SetDoubleVelocity(const double xVel, const double yVel){
	fXVel = xVel;
	fYVel = yVel;
}

/**
 * Advances the ball 1 step, according to its velocity
 */

void bo::Ball::AdvanceBall(){
	this->SetPos(this->GetPos().GetX() + fXVel, this->GetPos().GetY() + fYVel);
}

